﻿#region namespaces

using System;
using System.Linq;
using System.Reflection;
using System.Xml.Serialization;

#endregion

namespace ZOIL.DataModel
{
    public static class TypeExtensions
    {
        public static void ExchangeFieldsOnFirstLevel(this Type t, object rootObject, object exchangeObject)
        {
            ExchangeFieldsOnFirstLevel(t, rootObject, exchangeObject, null);
        }

        public static void ExchangeFieldsOnFirstLevel(this Type t, object rootObject, object exchangeObject, string[] additionalExcludedFields)
        {
            if (t == null)
            {
                return;
            }

            //base-klassen nach oben laufen da nur jeweils selber implementierte bei GetFields gefunden werden
            ExchangeFieldsOnFirstLevel(t.BaseType, rootObject, exchangeObject, additionalExcludedFields);

            //austauschen
            //->alle felder austauschen
            //alle Felder durchgehen und abgleichen
            foreach (FieldInfo field in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                //kein austausch wenn XmlIgnore
                if (field.GetCustomAttributes(typeof(XmlIgnoreAttribute), true).Length > 0)
                {
                    continue;
                }

                //keine delegates austauschen
                var bt = field.FieldType.BaseType;
                if (bt == typeof(Delegate) || (bt != null && bt.IsSubclassOf(typeof(Delegate))))
                {
                    continue;
                }

                if (additionalExcludedFields != null && additionalExcludedFields.Contains(field.Name))
                {
                    continue;
                }

                var newValue = field.GetValue(exchangeObject);
                field.SetValue(rootObject, newValue);
            }
        }

        public static void ExchangeFieldsOnFirstLevel(this object rootObject, object exchangeObject, string[] additionalExcludedFields)
        {
            ExchangeFieldsOnFirstLevel(rootObject.GetType(), rootObject, exchangeObject, additionalExcludedFields);
        }
    }
}